package com.wdy.dao.impl;

import java.sql.SQLException;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.wdy.dao.ChargeDao;
import com.wdy.po.Charge;
import com.wdy.util.TypeUtil;
import com.wdy.vo.Condition;
import com.wdy.vo.Page;

@SuppressWarnings("unchecked")
public class ChargeDaoHibernateImpl extends HibernateDaoSupport implements
		ChargeDao {

	private static final Log log = LogFactory
			.getLog(ChargeDaoHibernateImpl.class);
	private static final String DATE = "date";

	// hibernate.lock

	public void attachClean(Charge instance) {
		log.info("attaching clean Charge instance");
		try {
			getHibernateTemplate().lock(instance, LockMode.NONE);
			log.info("attach successful");
		} catch (DataAccessException e) {
			log.error("attach failed", e);
			throw e;
		}
	}

	// hibernate.saveOrUpdate

	public void attachDirty(Charge instance) {
		log.info("attaching dirty Charge instance");
		try {
			getHibernateTemplate().saveOrUpdate(instance);
			log.info("attach successful");
		} catch (DataAccessException e) {
			log.error("attach failed", e);
			throw e;
		}

	}

	// hibernate.delete

	public void delete(Charge persistentInstance) {
		log.info("deleting Charge instance");
		try {
			getHibernateTemplate().delete(persistentInstance);
			log.info("delete successful");
		} catch (DataAccessException e) {
			log.error("delete failed", e);
			throw e;
		}

	}

	// hibernate.find

	public List<Charge> findAll() {
		log.info("finding all");
		try {
			String queryString = "from Charge";
			List<Charge> result = (List<Charge>) getHibernateTemplate().find(
					queryString);
			log.info("find all successful,result size: " + result.size());
			return result;
		} catch (DataAccessException e) {
			log.error("find all failed", e);
			throw e;
		}
	}

	// hibernate.findByExample

	public List<Charge> findByExample(Charge instance) {
		log.info("finding Charge instance by example");
		try {
			List<Charge> result = (List<Charge>) getHibernateTemplate()
					.findByExample(instance);
			log
					.info("find Charge instance by example successful, result size: "
							+ result.size());
			return result;
		} catch (DataAccessException e) {
			log.error("find Charge instance by example failed", e);
			throw e;
		}
	}

	// hibernate.findById

	public Charge findById(Integer id) {
		log.info("finding Charge instance by id");
		try {
			Charge charge = (Charge) getHibernateTemplate().get(Charge.class,
					id);
			log.info("find Charge instance by id successful");
			return charge;
		} catch (DataAccessException e) {
			log.error("find Charge instance by id failed", e);
			throw e;
		}
	}

	// hibernate.find

	public List<Charge> findByProperty(String propertyName, Object value) {
		log.info("finding Charge instance with property: " + propertyName
				+ ", value: " + value);
		String queryString = "from Charge as model where model." + propertyName
				+ "=?";
		try {
			List<Charge> result = (List<Charge>) getHibernateTemplate().find(
					queryString, value);
			log
					.info("find Charge instance by property successful, result size: "
							+ result.size());
			return result;
		} catch (DataAccessException e) {
			log.error("find Charge instance by property failed", e);
			throw e;
		}
	}

	// findByProperty

	public List<Charge> findByDate(String value) {
		return findByProperty(DATE, value);
	}

	// hibernate.merge

	public Charge merge(Charge detachedInstance) {
		log.info("merging Charge instance");
		try {
			Charge user = (Charge) getHibernateTemplate().merge(
					detachedInstance);
			log.info("merge Charge successful");
			return user;
		} catch (DataAccessException e) {
			log.error("merge Charge failed", e);
			throw e;
		}
	}

	// hibernate.save

	public void save(Charge transientInstance) {
		log.info("saving Charge instance");
		try {
			getHibernateTemplate().save(transientInstance);
			log.info("save Charge instance successful");
		} catch (DataAccessException e) {
			log.error("save Charge instance failed", e);
			throw e;
		}
	}

	@Override
	public DetachedCriteria getCriteria(List<Condition> conList) {
		// TODO Auto-gene}rated method stub
		DetachedCriteria detachedCriteria = DetachedCriteria
				.forClass(Charge.class);
		for (Condition con : conList) {
			String propertyName = con.getPropertyName();
			String relation = con.getRelation();
			Object[] tempArray = con.getValues();
			Object[] values = new Object[tempArray.length];
			int[] types = con.getTypes();
			values = TypeUtil.getType(tempArray, types);

			if ("eq".equals(relation)) {
				detachedCriteria.add(Restrictions.eq(propertyName, values[0]));
			} else if ("like".equals(relation)) {
				detachedCriteria.add(Restrictions.ilike(propertyName, "%"
						+ values[0] + "%"));
			} else if ("in".equals(relation)) {
				detachedCriteria.add(Restrictions.in(propertyName, values));
			} else if ("between".equals(relation)) {
				detachedCriteria.add(Restrictions.between(propertyName,
						values[0], values[1]));
			} else if ("ge".equals(relation)) {
				detachedCriteria.add(Restrictions.ge(propertyName, values[0]));
			} else if ("le".equals(relation)) {
				detachedCriteria.add(Restrictions.le(propertyName, values[0]));
			} else if ("ne".equals(relation)) {
				detachedCriteria.add(Restrictions.ne(propertyName, values[0]));
			}
		}
		return detachedCriteria;
	}

	@Override
	public List query(List<Condition> conList, final Page page) {
		// TODO Auto-generated method stub
		log.info("querying multiple for Charge instances");
		final DetachedCriteria detachedCriteria = getCriteria(conList);
		List result = (List) getHibernateTemplate().execute(
				new HibernateCallback() {
					@Override
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						// TODO Auto-generated method stub
						Criteria criteria = detachedCriteria
								.getExecutableCriteria(session);
						criteria.setFirstResult(page.getBeginIndex());
						criteria.setMaxResults(page.getEveryPage());
						criteria.addOrder(Order.asc("cid"));
						criteria.setProjection(null);
						return criteria.list();
					}
				});
		return result;
	}

	@Override
	public List query(List<Condition> conList) {
		// TODO Auto-generated method stub
		log.info("querying multiple for Charge instances without pagination");
		final DetachedCriteria detachedCriteria = getCriteria(conList);
		List result = (List) getHibernateTemplate().execute(
				new HibernateCallback() {
					@Override
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						// TODO Auto-generated method stub
						Criteria criteria = detachedCriteria
								.getExecutableCriteria(session);
						criteria.setProjection(null);
						return criteria.list();
					}
				});
		return result;
	}

	@Override
	public int getQueryCount(List<Condition> conList) {
		// TODO Auto-generated method stub
		final DetachedCriteria detachedCriteria = getCriteria(conList);
		List result = (List) getHibernateTemplate().execute(
				new HibernateCallback() {
					@Override
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						// TODO Auto-generated method stub
						Criteria criteria = detachedCriteria
								.getExecutableCriteria(session);
						criteria.setProjection(null);
						return criteria.list();
					}
				});
		return result.size();
	}

	@Override
	public void deleteBatch(final Object[] objects) {
		// TODO Auto-generated method stub
		getHibernateTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				// TODO Auto-generated method stub
				String queryString = "delete from Charge where cid in (:cid)";
				Query query = session.createQuery(queryString);
				query.setParameterList("cid", objects);
				query.executeUpdate();
				return null;
			}
		});
	}

}
